package com.suray.rgv.son.mother.core;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.utils.LoggerType;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.ModuleType;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.exception.OrderExecuteException;
import com.suray.commin.exception.Rgv60TaskException;
import com.suray.rgv.data.Rgv60InfoData;
import com.suray.rgv.data.RgvSMInfoData;
import com.suray.rgv.son.core.RgvSonInfo;
import com.suray.rgv.son.mother.lock.LockManage;
import com.suray.rgv.son.mother.manual.RgvSonMoveBySpeedThread;
import com.suray.rgv.son.mother.util.RgvSMLogger;
import com.suray.rgv.son.util.RgvSonActionResult;
import com.suray.rgv60.core.Rgv60Core;
import com.suray.rgv60.exception.ExecTaskException;
import com.suray.rgv60.task.TaskInfo;
import com.suray.rgv60.util.Rgv60ErrorUtil;
import com.suray.rgv60.util.RgvTaskType;
import com.suray.type.Rgv60PalletStatus;
import com.suray.type.Rgv60Status;
import com.suray.type.RgvSonTaskResult;
import com.suray.wcs.res.enums.Order;
import com.suray.wcs.res.enums.PalletStatus;
import com.suray.wcs.res.enums.RgvStatus;
import suray.rgv.communication.data.status.DigitalOutput;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 子母车核心，继承Rgv60Core
 */
public class RgvSMCore extends Rgv60Core {
    //子车控制
    private RgvSonControl rgvSonControl;

    private RgvSonMoveBySpeedThread moveBySpeedThread;

    //子母车任务锁管理器
    private LockManage lockManage;

    private String serialNum;

    private RgvSMInfo rgvSMInfo;

    public RgvSMCore(int rgvNo, String serialNum) {
        super(rgvNo, serialNum, ModuleType.RGV_RES60);

        this.serialNum = serialNum;
        this.lockManage = new LockManage();

        rgvSMInfo = new RgvSMInfo(serialNum, getRgv60Info());

        rgvSonControl = new RgvSonControl(this, seerComm, serialNum);
        moveBySpeedThread = new RgvSonMoveBySpeedThread(rgvSonControl);
        moveBySpeedThread.start();
    }

    /**
     * 初始化小车数据
     */
    public void initParam(boolean simpleInit) throws IOException {
        super.initParam(simpleInit);
        rgvSonControl.init();
    }

    public synchronized void init(String ip) throws IOException {
        super.init(ip);
        rgvSonControl.init();
    }

    /**
     * 清除子车指令结果
     */
    private void clearSonRgvTaskResult() {
        if (rgvSonControl.getActionResult() != RgvSonActionResult.INIT.getValue()) {
            sonRgvConfirm("清除子车指令结果");
        }

        //如果不在母车内
        if (!isSonRgvInMother()) {

        }
    }

    @Override
    protected void init() {
        int tick = 2;
        while (true) {
            try {
                if (seerComm.routeOnLine()) {
                    checkLockRobot();
                }
            } catch (IOException e) {
                RgvSMLogger.error(LoggerType.INFO, serialNum, "初始化子车数据", "通讯异常", this.getClass());
            } catch (Exception e) {
                RgvSMLogger.error(LoggerType.INFO, serialNum, "初始化子车数据", e.getMessage(), this.getClass());
            }

            if (tick > 0) {
                tick--;
            } else {
                break;
            }

            WcsFuncUtil.delay(2000);
        }
    }

    @Override
    public boolean action(Order rgvActionType, Object param) throws IOException {
        switch (rgvActionType) {
            case PALLET_UP:
                palletUp(rgvActionType);
                return true;
            case PALLET_DOWN:
                palletDown(rgvActionType);
                return true;
            case CALIBRATION_PALLET:
                return rgvSonControl.palletCalibration();
            default:
                break;
        }

        return super.action(rgvActionType, param);
    }

    @Override
    protected void process() {
        super.process();

        if (rgvSMInfo.rgv60Info.isOnLine()) {
            rgvSMInfo.analyzeRobotIO();
        } else {
            setRgvStatus(Rgv60Status.OFF_LINE);
        }
    }

    @Override
    public boolean isOnLine() {
        if (rgvSonControl.isSonRgvEnable() && !rgvSonControl.isOnline()) {
            return false;
        }

        return super.isOnLine();
    }

    /**
     * 生成子车任务 -- 新
     * @param taskId
     * @param resTaskNo
     * @param nodeList
     * @param pathIndexs
     * @param startTask
     */
    public void generalSonRgvTask(Object taskId, int resTaskNo, List<Node> nodeList, int[] pathIndexs,
                                  boolean startTask) throws IOException {
        try {
            if (rgvSonControl.getRgvStatus() == RgvStatus.CHARGING) {
                sonRgvStopCharge();
            }
            if (rgvSonControl.getRgvStatus() != RgvStatus.READY) {
                throw new RuntimeException(serialNum + "子车未就绪，不能执行任务");
            }
            RgvSMLogger.info(LoggerType.INFO, resTaskNo, serialNum, "给子车发送任务", this.getClass());
            lock(rgvSonControl.getSeries());
            if (!isAllSendTaskEnd() && startTask) {
                throw new Rgv60TaskException("母车任务未执行完毕，不能执行子车任务");
            }
            TaskInfo task = new TaskInfo(taskId, nodeList, serialNum, RgvTaskType.SON_TASK);
            tasks.add(task);
            doSonRgvTaskNew(taskId, resTaskNo, nodeList, pathIndexs, startTask);
            //子车任务完成
            checkTask(tasks, task);
        } finally {
            releaseLock(rgvSonControl.getSeries());
        }
    }

    /**
     * 获取已完成的段序号
     * @param resTaskId
     * @param taskTime
     * @return
     */
    public int getRgvSonEndSegment(int resTaskId, long taskTime) {
        if (taskTime < rgvSonControl.getRgvSonDataTime() && resTaskId == rgvSonControl.getRgvCurTaskId()) {
            return rgvSonControl.getRgvTaskEndSegment();
        }

        return 0;
    }

    /**
     * 任务是否结束
     *
     * @param wcsTaskId
     * @param resTaskId
     * @param taskTime
     * @return
     */
    public boolean isRgvSonTaskEnd(int wcsTaskId, int resTaskId, long taskTime) {
//        checkError();

        if (taskTime < rgvSonControl.getRgvSonDataTime() && resTaskId == rgvSonControl.getRgvCurTaskId()) {
            if (rgvSonControl.getRgvSonTaskResult() == RgvSonTaskResult.SUCCESS) {
                List<TaskInfo> endTasks = new ArrayList<>();
                for (TaskInfo task : tasks) {
                    if (task.getTaskId().equals(wcsTaskId)) {
                        endTasks.add(task);
                    }
                }

                tasks.removeAll(endTasks);
                return true;
            } else if (rgvSonControl.getErrorCode() != 0) {
                throw new OrderExecuteException(rgvNo, rgvSonControl.getErrorCode());
            }
        }
        return false;
    }

    /**
     * 加锁
     */
    private void lock(Object key) {
        if (!lockManage.getLock(key, this)) {
            throw new Rgv60TaskException("子车或母车已锁定任务, 当前无法上锁：" + key);
        }
    }

    /**
     * 解锁
     */
    private void releaseLock(Object key) {
        lockManage.releaseLock(key);
    }

    /**
     * 子车上送错误，主动检测需要刷新子车状态，效率低
     */
    public void checkSonRgvCanDoTask() {
//        if (!sonRgv.checkSonRgvStatusCanDoTask()) {
//            throw new Rgv60TaskException("子车当前状态无法执行任务:未就绪或任务结果未清除，请在子车手动操作中点击子车故障恢复按钮");
//        }
    }

    /**
     * 检测母车任务
     * 如果母车任务Id与子车任务id一致，则母车任务自动切换为完成。
     * @param tasks
     * @param task
     * @return
     */
    private void checkTask(List<TaskInfo> tasks, TaskInfo task) {
        if (task.getTaskType() == RgvTaskType.SON_TASK) {
            for (TaskInfo taskInfo : tasks) {
                if (taskInfo.getTaskId().equals(task.getTaskId())) {
                    tasks.remove(taskInfo);
                    task = taskInfo;
                    break;
                }
            }
        }

        if (task == null) {
            return;
        }
        endTask(task);
    }

    private void doSonRgvTaskNew(Object taskId, int rgvSonTaskId, List<Node> nodeList, int[] pathIndexs,
                                 boolean startTask) throws IOException {
        rgvInterrupt("sonRgvSendTask new");
        rgvSonControl.doSonRgvTaskNew(taskId, rgvSonTaskId, nodeList, pathIndexs, startTask);
        LoggerUtil.info(serialNum + " 子车任务" + rgvSonTaskId + "完成:" + taskId, this.getClass());
    }

    /**
     * 小车方向
     * x增大方向
     * 为右：true
     * 为左：false
     */
    public void setRgvDirectionX(Boolean rgvDirection) {
        rgvSonControl.setRgvDirectionX(rgvDirection);
    }

    /**
     * 小车方向
     * y增大方向
     * 为右：true
     * 为左：false
     */
    public void setRgvDirectionY(Boolean rgvDirection) {
        rgvSonControl.setRgvDirectionY(rgvDirection);
    }

    /**
     * 行驶任务
     * @param taskId
     * @param nodes
     * @return
     */
    public boolean task(Object taskId, List<Node> nodes) {
        try {
            lock(serialNum);
            return super.task(taskId, nodes);
        } finally {
            releaseLock(serialNum);
        }
    }

    /**
     * 查询机器人信息
     * @throws IOException
     */
    protected void checkRobotInfo() throws IOException {
        super.checkRobotInfo();
        switch (rgvSonControl.getRgvPalletStatus()) {
            case DOWN:
                setPalletStatus(Rgv60PalletStatus.DOWN_OK);
                break;
            case UP:
                setPalletStatus(Rgv60PalletStatus.UP_OK);
                break;
            case ERROR:
                setPalletStatus(Rgv60PalletStatus.ERROR);
                break;
            case UNKNOWN:
            default:
                setPalletStatus(Rgv60PalletStatus.INVALID);
                break;

        }

        if (getRgvStatus() == Rgv60Status.STANDY) {
            if (rgvSonControl.isSonRgvEnable() && rgvSonControl.getRgvStatus() == RgvStatus.RUNING) {
                setRgvStatus(Rgv60Status.SON_RGV_RUNNING);
            } else if (rgvSonControl.isSonRgvEnable() && rgvSonControl.getRgvStatus() == RgvStatus.NODE_STANDBY) {
                setRgvStatus(Rgv60Status.SON_RGV_WAITING);
            }
        }
    }

    /**
     * 结束充电
     */
    protected void endCharge() {
        //sonRgvStopCharge();
        try {
            seerComm.setDigitalOutputStatsForRobot(new DigitalOutput(9,false));
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
        }
    }

    /**
     * 开始充电
     */
    protected void startCharge() {
        //sonRgvCharge();
        try {
            seerComm.setDigitalOutputStatsForRobot(new DigitalOutput(9,true));
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
        }
    }

    /**
     * 托盘升
     * @param rgvActionType
     * @throws IOException
     */
    protected void palletUp(Order rgvActionType) throws IOException {
        RgvSMLogger.info(LoggerType.ACTION, rgvActionType.getOrderByte(), serialNum, "托盘上升",
                this.getClass());
        checkSonRgvCanDoTask();
        rgvSonControl.palletUp(null);

        if (rgvSonControl.getRgvPalletStatus() != PalletStatus.UP) {
            throw new Rgv60TaskException("托盘上升执行完成，但是托盘状态不是顶升");
        }

        RgvSMLogger.info(LoggerType.ACTION, rgvActionType.getOrderByte(), serialNum, "托盘上升成功",
                this.getClass());
    }

    /**
     * 托盘降
     * @param rgvActionType
     * @throws IOException
     */
    protected void palletDown(Order rgvActionType) throws IOException {
        RgvSMLogger.info(LoggerType.ACTION, rgvActionType.getOrderByte(), serialNum, "托盘下降",
                this.getClass());
        checkSonRgvCanDoTask();
        rgvSonControl.palletDown(null);

        if (rgvSonControl.getRgvPalletStatus() != PalletStatus.DOWN) {
            throw new Rgv60TaskException("托盘下降执行完成，但是托盘状态不是下降");
        }

        RgvSMLogger.info(LoggerType.ACTION, rgvActionType.getOrderByte(), serialNum, "托盘下降成功",
                this.getClass());
    }

    /**
     * 子车动作结果确认
     * @param des
     */
    private void sonRgvConfirm(String des) {
        rgvSonControl.sonRgvConfirm(des);
    }

    public boolean isAllSendTaskEnd() {
        for (TaskInfo task : tasks) {
            if (!task.isAllTaskEnd()) {
                return false;
            }
        }

        return true;
    }

    /**
     * 清除故障
     */
    public void clearError() throws IOException {
        if (rgvSonControl.isSonRgvEnable()) {
            try {
                clearSonRgvTaskResult();
            } catch (Exception e) {
                RgvSMLogger.warn(LoggerType.ERROR, serialNum, "子车清除任务失败", e.getMessage(), this.getClass());
            }
            rgvSonControl.clearError();
        }
        super.clearError();
    }

    /**
     * 设置中断
     */
    public void setInterrupt() throws IOException {
        rgvSonControl.setInterrupt();
        super.setInterrupt();
    }

    /**
     * 子母车是否静止
     * @return
     */
    @Override
    public boolean isStatic() {
        return super.isStatic() && (!rgvSonControl.isSonRgvEnable() || rgvSonControl.isSonRgvStatic());
    }

    /**
     * 获取小车信息
     * @return
     */
    public RgvSMInfoData getRgv60InfoData() {
        RgvSMInfoData rgvSMInfoData = new RgvSMInfoData();
        Rgv60InfoData rgv60InfoData = super.getRgv60InfoData();
        rgvSMInfoData.setCurrentStation(rgv60InfoData.getCurrentStation());
        rgvSMInfoData.setRelocStatus(rgv60InfoData.getRelocStatus());
        rgvSMInfoData.setRobotCurrentStation(rgv60InfoData.getRobotCurrentStation());
        rgvSMInfoData.setLastStation(rgv60InfoData.getLastStation());
        rgvSMInfoData.setSerialNum(rgvSMInfo.series);
        rgvSMInfoData.setOnLine(rgv60InfoData.isOnLine());
        rgvSMInfoData.setRouteOnLine(rgv60InfoData.isRouteOnLine());
        rgvSMInfoData.setConfigOnLine(rgv60InfoData.isConfigOnLine());
        rgvSMInfoData.setControlOnLine(rgv60InfoData.isControlOnLine());
        rgvSMInfoData.setRobotStateOnLine(rgv60InfoData.isRobotStateOnLine());
        rgvSMInfoData.setHasRgvAuthor(rgv60InfoData.isHasRgvAuthor());
        rgvSMInfoData.setRgvStatus(rgv60InfoData.getRgvStatus());
        rgvSMInfoData.setRgvActStatus(rgv60InfoData.getRgvActStatus());
        rgvSMInfoData.setErrorInfos(rgv60InfoData.getErrorInfos());
        rgvSMInfoData.setHighestError(rgv60InfoData.getHighestError());
        rgvSMInfoData.setPalletStatus(rgv60InfoData.getPalletStatus());
        rgvSMInfoData.setPalletEnable(rgv60InfoData.getPalletEnable());
        rgvSMInfoData.setPalletActionErrorCode(rgv60InfoData.getPalletActionErrorCode());
        rgvSMInfoData.setHasCargo(rgv60InfoData.getHasCargo());
        rgvSMInfoData.setX(rgv60InfoData.getX());
        rgvSMInfoData.setY(rgv60InfoData.getY());
        rgvSMInfoData.setAngle(rgv60InfoData.getAngle());
        rgvSMInfoData.setConfidence(rgv60InfoData.getConfidence());
        rgvSMInfoData.setBlocked(rgv60InfoData.getBlocked());
        rgvSMInfoData.setBatSoc(rgv60InfoData.getBatSoc());
        rgvSMInfoData.setBatTemp(rgv60InfoData.getBatTemp());
        rgvSMInfoData.setBatVolt(rgv60InfoData.getBatVolt());
        rgvSMInfoData.setBatCur(rgv60InfoData.getBatCur());
        rgvSMInfoData.setAutoCharge(rgv60InfoData.getAutoCharge());
        rgvSMInfoData.setCharging(rgv60InfoData.getCharging());
        rgvSMInfoData.setTaskStatus(rgv60InfoData.getTaskStatus());
        rgvSMInfoData.setTargetStation(rgv60InfoData.getTargetStation());
        rgvSMInfoData.setTaskType(rgv60InfoData.getTaskType());
        rgvSMInfoData.setLoadMapStatus(rgv60InfoData.getLoadMapStatus());
        rgvSMInfoData.setMode(rgv60InfoData.getMode());
        rgvSMInfoData.setRollerMode(rgv60InfoData.getRollerMode());
        rgvSMInfoData.setCurrentMap(rgv60InfoData.getCurrentMap());
        rgvSMInfoData.setCurrentMapMD5(rgv60InfoData.getCurrentMapMD5());
        rgvSMInfoData.setWifiStrength(rgv60InfoData.getWifiStrength());
        rgvSMInfoData.setRobotName(rgv60InfoData.getRobotName());
        rgvSMInfoData.setMaps(rgv60InfoData.getMaps());
        rgvSMInfoData.setOdo(rgv60InfoData.getOdo());
        rgvSMInfoData.setTodayOdo(rgv60InfoData.getTodayOdo());
        rgvSMInfoData.setRunningTime(rgv60InfoData.getRunningTime());
        rgvSMInfoData.setCurRunningTime(rgv60InfoData.getCurRunningTime());
        rgvSMInfoData.setControlVolt(rgv60InfoData.getControlVolt());
        rgvSMInfoData.setControlTemp(rgv60InfoData.getControlTemp());
        rgvSMInfoData.setControlWet(rgv60InfoData.getControlWet());
        rgvSMInfoData.setChargeNum(rgv60InfoData.getChargeNum());
        rgvSMInfoData.setPermitMaxChgVolt(rgv60InfoData.getPermitMaxChgVolt());
        rgvSMInfoData.setPermitMaxChgCur(rgv60InfoData.getPermitMaxChgCur());
        rgvSMInfoData.setBlockX(rgv60InfoData.getBlockX());
        rgvSMInfoData.setBlockY(rgv60InfoData.getBlockY());
        rgvSMInfoData.setDriveEmc(rgv60InfoData.getDriveEmc());
        rgvSMInfoData.setHoldBrake(rgv60InfoData.getHoldBrake());
        rgvSMInfoData.setIsStop(rgv60InfoData.getIsStop());
        rgvSMInfoData.setTargetX(rgv60InfoData.getTargetX());
        rgvSMInfoData.setTargetY(rgv60InfoData.getTargetY());
        rgvSMInfoData.setTargetR(rgv60InfoData.getTargetR());
        rgvSMInfoData.setRobotNote(rgv60InfoData.getRobotNote());
        rgvSMInfoData.setDI(rgv60InfoData.getDI());
        rgvSMInfoData.setDO(rgv60InfoData.getDO());

        rgvSMInfoData.setIsSonRgvEnable(rgvSonControl.isSonRgvEnable());
        RgvSonInfo rgvSonInfo = rgvSonControl.getRgvSonInfoData();
        if (rgvSonInfo != null) {
            rgvSMInfoData.setSonState(rgvSonInfo.getRgvStatus().toString());
            rgvSMInfoData.setSonCmd(rgvSonInfo.getActNo());
            rgvSMInfoData.setSonResult(rgvSonInfo.getActionResult().toString());
            rgvSMInfoData.setSonSpeed((int) rgvSonInfo.getCurSpeed());
            rgvSMInfoData.setSonAlarm(rgvSonInfo.getWarnCode());
            rgvSMInfoData.setSonError(rgvSonInfo.getErrorCode());
            rgvSMInfoData.setSonBcr(rgvSonInfo.getGroundCode());
            rgvSMInfoData.setSonEle(rgvSonInfo.getSoc());
            rgvSMInfoData.setSonMoveSpeed((int) rgvSonInfo.getRunSpeed());
            rgvSMInfoData.setSonMoveAcc((int) rgvSonInfo.getRunAcc());
            rgvSMInfoData.setSonMoveDec((int) rgvSonInfo.getRunDec());
            rgvSMInfoData.setCurActionNo(rgvSonControl.getCurActionNo());
            rgvSMInfoData.setMotherRgvGroundCode(rgvSonInfo.getPlatformGroundCode());
            rgvSMInfoData.setHasSonRgv(isSonRgvInMotherNoComm());
            rgvSMInfoData.setLeftRgvSignal(rgvSMInfo.leftRgvSignal);
            rgvSMInfoData.setRightRgvSignal(rgvSMInfo.rightRgvSignal);
            rgvSMInfoData.setRgvSonTaskStatus(rgvSonInfo.getTaskStatus().toString());
            rgvSMInfoData.setRgvSonTaskId(rgvSonInfo.getTaskId());
            rgvSMInfoData.setRgvSonFinishSegment(rgvSonInfo.getFinishSegment());
            rgvSMInfoData.setRgvSonTaskResult(rgvSonInfo.getTaskResult().toString());
            rgvSMInfoData.setRgvSonTaskErrorCode(rgvSonInfo.getTaskErrorCode());
            rgvSMInfoData.setRgvSonDataTime(rgvSonInfo.getTime());
        }
        return rgvSMInfoData;
    }

    /**
     * 写入地图节点
     * @param nodes
     */
    public void setMapNodes(List<Node> nodes) {
        rgvSMInfo.mapNodes = nodes;
    }

    /**
     * 更新地图节点信息
     * @param node
     */
    public void updateMapNode(Node node) {
        for (Node mapNode : rgvSMInfo.mapNodes) {
            if (mapNode.equals(node)) {
                updateNode(mapNode, node);
                break;
            }
        }
    }

    /**
     * 节点信息更新
     * @param mapNode
     * @param node
     */
    private void updateNode(Node mapNode, Node node) {
        if (node.findOffX() != null) {
            mapNode.setOffsetX(node.findOffX());
        }
        if (node.findOffY() != null) {
            mapNode.setOffsetY(node.findOffY());
        }
        if (node.getRgv60Point() != null) {
            mapNode.setRgv60Point(node.getRgv60Point());
        }
        if (node.getGroundCode() != null) {
            mapNode.setGroundCode(node.getGroundCode());
        }
        if (node.getSonRgvGroundCode() != null) {
            mapNode.setSonRgvGroundCode(node.getSonRgvGroundCode());
        }
    }

    public void initNet(String ip) {
        seerComm.initNet(ip);
    }

    /**
     * 子车是否在母车里面
     * 通过光电判断, 如果子车在线还要判断子车扫到的条码是否在母车内
     * 子车条码是否需要添加有效时间，子车的数据不是实时获取
     * 如果子车条码过了有效时间，则忽略当前条码信息，重新获取子车信息，
     * 如果子车信息获取失败，忽略条码只判断光电信号 -- 感觉有问题，不做这个策略
     * @return
     */
    public boolean isSonRgvInMother() {
        //禁用子车后不判断子车是否在母车内，返回true
        if (!rgvSonControl.isSonRgvEnable()) {
            return true;
        }

        //两个光电起码有一个未检测到子车，返回不在母车内
        if (!rgvSMInfo.hasSonRgv) {
            RgvSMLogger.info(LoggerType.ERROR, serialNum, "子车不在母车内", "光电未检测到子车", this.getClass());
            return false;
        }

        return rgvSonControl.isInMother();
    }

    /**
     * 获取子车地码
     * @return
     */
    public String getSonRgvGroundCode() {
        return rgvSonControl.getGroundCode();
    }

    /**
     * 子车按速度行驶
     * @param direction
     */
    public void sonRgvMoveBySpeed(Integer direction) {
        moveBySpeedThread.startSpeedMove(direction);
    }

    /**
     * 子车按速度停止
     */
    public void stopSonRgvMoveBySpeed() {
        moveBySpeedThread.stopSpeedMove();
    }

    public void sonRgvMoveByDistance(Integer direction) {
        rgvSonControl.sonRgvMoveByDistance(direction);
    }

    public void sonRgvRecovery() {
        rgvSonControl.sonRgvRecovery();
    }

    /**
     * 子车充电
     */
    public void sonRgvCharge() {
//        rgvSonControl.sonRgvCharge();
    }

    /**
     * 子车停止充电
     */
    public void sonRgvStopCharge() {
//        rgvSonControl.sonRgvStopCharge();
    }

    public void sonRgvChangeSpeedConfig(Integer moveSpeed, Integer moveSpeedAcc, Integer moveSpeedDec) {
        rgvSonControl.sonRgvChangeSpeedConfig(moveSpeed, moveSpeedAcc, moveSpeedDec);
    }

    public void sonRgvCalibration() {
        rgvSonControl.sonRgvCalibration();
    }

    /**
     * 获取母车上子车条码
     * @return
     */
    public String getSonGroundCodeInMother() {
        return rgvSonControl.getSonGroundCodeInMother();
    }

    public void setSonGroundCodeInMother(String sonGroundCodeInMother) {
        rgvSonControl.setSonGroundCodeInMother(sonGroundCodeInMother);
    }

    /**
     * 结束任务
     * @param taskId
     */
    public void endTask(Object taskId) {
        for (TaskInfo task : tasks) {
            if (task.getTaskId().equals(taskId)) {
                endTask(task);
                break;
            }
        }
    }

    /**
     * 清除子车任务
     */
    public void sonRgvClearTask() {
        sonRgvConfirm("清除任务结果");
    }

    public RgvStatus getSonRgvStatus() {
        return rgvSonControl.getRgvStatus();
    }

    public void enableSonRgv() {
        rgvSonControl.enableSonRgv();
    }

    public void disableSonRgv() {
        rgvSonControl.disableSonRgv();
    }

    public boolean isMotherOnline() {
        return seerComm.isOnLine();
    }

    public boolean isSonRgvInMotherNoComm() {
        return rgvSMInfo.hasSonRgv && rgvSonControl.isLastGroundCodeInMother();
    }

    public int getSonRgvTaskErrorCode() {
        return rgvSonControl.getTaskErrorCode();
    }

    public boolean isSonRgvTaskError() {
        return rgvSonControl.getTaskErrorCode() != 0;
    }

    /**
     * 更改子车
     * @param rgvSon
     */
    public void changeSonRgv(Object rgvSon) {
        rgvSonControl.changeSonRgv(rgvSon);
    }

    public void sonRgvTaskStart() throws IOException {
        rgvSonControl.taskStart();
    }

    class TaskInfoContainer {
        TaskInfo task;
        List<String> rgvTaskIds;

        TaskInfoContainer(TaskInfo task, List<String> rgvTaskIds) {
            this.task = task;
            this.rgvTaskIds = rgvTaskIds;
        }
    }

    /**
     * 任务处理
     */
    private void analyzeTask() throws IOException {
        //无任务
        if (tasks.size() == 0) {
            return;
        }

//        //故障状态
//        if (rgvSMInfo.rgvStatus.equals(Rgv60Status.ERROR)) {
//            return;
//        }

        try {
            TaskInfo task = tasks.get(0);
            if (!task.checkTaskEnd(rgvSMInfo.rgv60Info.getCurrentStation())) {
                doTask(task);
            } else {
                endTask(task);
            }
        } catch (ExecTaskException e) {
            setRgvError(Rgv60ErrorUtil.PERFORM_TASK_ERROR.getCode(),
                    Rgv60ErrorUtil.PERFORM_TASK_ERROR.getDes(),
                    Rgv60ErrorUtil.PERFORM_TASK_ERROR.getLevel());
        }
    }

    /**
     * 获取子母车电量
     * @return
     */
    public Float getBatSoc() {
        if (rgvSonControl.isSonRgvEnable()) {
            float soc = super.getBatSoc();
            float sonSoc = rgvSonControl.getBatSoc();
            return Math.min(soc, sonSoc);
        } else {
            return super.getBatSoc();
        }
    }

    @Override
    public String toString() {
        return serialNum;
    }
}
